<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\BaseController;
use App\Jobs\ArticleStarSubscribe;
use App\Jobs\ArticleWeight;
use App\Models\Article;
use App\Models\Circle;
use App\Models\Comment;
use App\Models\Star;
use App\Models\Subscribe;
use App\Models\User;
use App\Services\BalanceService;
use App\Services\NotifyService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Redis;

class StarController extends BaseController
{

    public $model = Star::class;

    /**
     * 评论
     * @param Request $request
     * @param $user
     * @return mixed
     * @throws \Illuminate\Validation\ValidationException
     * @throws \Throwable
     */
    public function store(Request $request, $user = null) {
        $this->validate($request, [
            'entity_id' => 'required',
            'type' => 'required|in:1,2'
        ]);
        $user = $user?: $this->getUser();
        $input = $request->input();

        $cache_key = 'star_lock_' . $user->id;
        if (Redis::setnx($cache_key, 1)) {
            Redis::expire($cache_key, 3);
            try {
                return \DB::transaction(function () use($input, $user, $cache_key){
                    if ($input['type'] == Star::TYPE_COMMENT) {
                        $entity_model = new Comment();
                    } else {
                        $entity_model = new Article();
                    }
                    $entity_result = $entity_model->find($input['entity_id']);
                    if (!$entity_result)
                        return $this->failed("ID对应数据不存在");

                    $input['user_id'] = $user->id;
                    $input['entity_user_id'] = $entity_result->user_id;
                    $is_first = 0;

                    $one = (new $this->model)->where('user_id', $user->id)->where('entity_id', $input['entity_id'])
                        ->where('type', $input['type'])->first();
                    if ($one) {
                        $one->delete();
                        $star = 'cancel';
                    } else {
                        $star = 'ok';
                        if ($input['type'] == Star::TYPE_COMMENT) {
                            $entity_id = $entity_result->entity_id;
                            $comment_id = $input['entity_id'];
                            $content = $entity_result->message;
                            $input['article_id'] = $entity_id;
                            $input['article_user_id'] = $entity_result->entity_user_id;
                            $input['child_type'] = 4;
                            Article::where('id', $entity_id)->update([
                                'latest_comment_at' => time()
                            ]);
                        } else {
                            $entity_id = $input['entity_id'];
                            $input['article_id'] = $entity_id;
                            $input['article_user_id'] = $entity_result->user_id;
                            $input['child_type'] = $entity_result->type;
                            $comment_id = 0;
                            $content = $entity_result->title;

                            if (Star::TYPE_ARTICLE == $input['type']) {
                                $exists = Subscribe::where('user_id', $input['entity_user_id'])->where('template_id', Subscribe::TEMPLATE_ARTICLE_STAR)->exists();
                                if ($exists && $input['user_id'] != $input['entity_user_id'])
                                    $this->dispatch(new ArticleStarSubscribe($entity_id));

                                if ($user->is_virtual) {
                                    $entity_result->pv += 5;
                                }
                            }
                        }
                        $this->model::create($input);
                        $type = Star::TYPE_COMMENT == $input['type'] ? 7 : 1;
                        NotifyService::store($input['user_id'], $type, $entity_id, $input['entity_user_id'], $content, $comment_id);

                        $exists = BalanceService::star($user->id);
                        $is_first = !$exists ? 1 : 0;

                    }
                    $num = ($star == 'ok' ? 1 : -1);


                    $entity_result->star_num = $entity_result->star_num + $num;
                    if ($input['type'] == Star::TYPE_ARTICLE && $activity_id = $entity_result->activity_id) {
                        $circle = Circle::find($activity_id);
                        if (time() <= strtotime($circle->activity_end_at)) {
                            $entity_result->activity_star_num += $num;
                            if ($entity_result->activity_star_num < 0)
                                $entity_result->activity_star_num = 0;
                        }
                    }
                    $entity_result->save();

                    if ($input['type'] == Star::TYPE_ARTICLE)
                        $this->dispatch(new ArticleWeight($input['entity_id']));


                    Redis::del($cache_key);

                    return $this->success([
                        'star' => $star,
                        'is_first' => $is_first
                    ]);

                });
            } catch (\Exception $e) {
                Redis::del($cache_key);
                return $this->failed($e->getMessage());
            }
        }

    }

}

